#include "uspinbox.h"
#include "ustylebutton.h"

#include <QPainter>
#include <QPainterPath>
#include <QApplication>
#include <QHBoxLayout>

void updateState(bool up, QAbstractSpinBox *spinBox)
{
    Q_ASSERT(spinBox);
    int steps = up ? 1 : -1;
    if (QApplication::keyboardModifiers() & Qt::ControlModifier)
        steps *= 10;
    spinBox->stepBy(steps);
}

USpinBox::USpinBox(QWidget* parent, SpinBoxType type) : QWidget(parent)
    , m_type(type)
{
    QSpinBox *box = new QSpinBox(this);
    box->setButtonSymbols(QSpinBox::NoButtons);
    box->setFrame(false);
    box->setObjectName("uspinBox_box");
    m_spinBox = box;
    m_spinBox->installEventFilter(this);

    QVBoxLayout *buttonLayout = new QVBoxLayout;
    buttonLayout->setContentsMargins(0,0,0,0);
    buttonLayout->setSpacing(1);

    buttonLayout->addWidget(creatButton(RadiuPosition::Top));
    buttonLayout->addWidget(creatButton(RadiuPosition::Bottom));

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->setContentsMargins(2,2,2,2);
    mainLayout->addWidget(m_spinBox);
    mainLayout->addLayout(buttonLayout);
    setLayout(mainLayout);
}

USpinBox::~USpinBox()
{
}

void USpinBox::setRadius(int radius)
{
    if (m_radius != radius)
    {
        m_radius = radius;
        update();
    }
}

void USpinBox::setBackGroundColor(const QColor &color)
{
    if (m_color != color)
    {
        m_color = color;
        update();
    }
}

USpinBox::SpinBoxType USpinBox::type()
{
    return m_type;
}

QAbstractSpinBox *USpinBox::spinBox() const
{
    return m_spinBox;
}

void USpinBox::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

    QPainterPath rectPath;
    QRect rect = this->rect().adjusted(1.5, 1.5, -1.5, -1.5);
    rectPath.addRoundedRect(rect, m_radius, m_radius);
    painter.fillPath(rectPath, palette().color(QPalette::Button));

    if (m_spinBox->hasFocus())
    {
        painter.save();
        painter.setBrush(Qt::NoBrush);
        painter.setPen(QPen(palette().color(QPalette::Highlight), 1.5));
        painter.drawPath(rectPath);
        painter.restore();
    }
}

bool USpinBox::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == m_spinBox) {
        switch (event->type()) {
        case QEvent::FocusIn:
            update();
            break;
        case QEvent::FocusOut:
            update();
            break;
        default:
            break;
        }
    }

    return QWidget::eventFilter(watched, event);
}

QSize USpinBox::sizeHint() const
{
    return QSize(m_spinBox->sizeHint().width() + 10, 30);
}

QWidget *USpinBox::creatButton(const RadiuPosition &positon)
{
    auto button = new UStyleButton("", this);
    button->setFlat(true);
    button->setRadius(m_radius);
    button->setFocusPolicy(Qt::NoFocus);
    button->setRadiuPosition(positon);
    button->setMinimumHeight(14);
    button->setAutoRepeat(true);
    if (RadiuPosition::Top == positon) {
        button->setIcon(QIcon::fromTheme("utk_arrowup"));
        button->setObjectName("uspinBox_topbutton");
        connect(button, &UStyleButton::clicked, this, [=](){
            updateState(true, m_spinBox);
        });
    } else if (RadiuPosition::Bottom == positon) {
        button->setIcon(QIcon::fromTheme("utk_arrowdown"));
        button->setObjectName("uspinBox_bottombutton");
        connect(button, &UStyleButton::clicked, this, [=](){
            updateState(false, m_spinBox);
        });
    }

    return button;
}

